package hunan.qianyuan.codefatherback.core;

import cn.hutool.json.JSONUtil;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.service.TokenStream;
import dev.langchain4j.service.tool.ToolExecution;
import hunan.qianyuan.codefatherback.ai.AiCodeGeneratorService;
import hunan.qianyuan.codefatherback.ai.AiCodeGeneratorServiceFactory;
import hunan.qianyuan.codefatherback.ai.model.HtmlCodeResult;
import hunan.qianyuan.codefatherback.ai.model.MultiFileCodeResult;
import hunan.qianyuan.codefatherback.ai.model.enums.CodeGenTypeEnum;
import hunan.qianyuan.codefatherback.ai.model.message.AiResponseMessage;
import hunan.qianyuan.codefatherback.ai.model.message.ChatResult;
import hunan.qianyuan.codefatherback.ai.model.message.ToolExecutedMessage;
import hunan.qianyuan.codefatherback.ai.model.message.ToolRequestMessage;
import hunan.qianyuan.codefatherback.exception.BusinessException;
import hunan.qianyuan.codefatherback.exception.ErrorCode;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.io.File;
/**
 * AI 代码生成外观类，组合生成和保存功能
 */
@Service
@Slf4j
public class AiCodeGeneratorFacade {


//    @Resource
//    private AiCodeGeneratorService aiCodeGeneratorService;
    @Resource
    private AiCodeGeneratorServiceFactory aiCodeGeneratorServiceFactory;


    /**
     * 统一入口：根据类型生成并保存代码
     *
     * @param userMessage     用户提示词
     * @param codeGenTypeEnum 生成类型
     * @return 保存的目录
     */

    public Flux<String> generateAndSaveCodeStream(String userMessage, CodeGenTypeEnum codeGenTypeEnum,long appId) {
        if (codeGenTypeEnum == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "生成类型为空");
        }
        return switch (codeGenTypeEnum) {
            case HTML -> generateAndSaveHtmlCodeStream(userMessage,appId);
            case MULTI_FILE -> generateAndSaveMultiFileCodeStream(userMessage,appId);
            case VUE_PROJECT -> generateAndSaveVueProjectCodeStream(userMessage,appId);
            default -> {
                String errorMessage = "不支持的生成类型：" + codeGenTypeEnum.getValue();
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, errorMessage);
            }
        };
    }

    private Flux<String> generateStream(String userMessage, long appId) {
        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appId, CodeGenTypeEnum.HTML);
        Flux<String> result = aiCodeGeneratorService.generateHtmlCodeStream(userMessage);
        StringBuffer sb = new StringBuffer();
        return result.doOnNext(codeContent -> {
            sb.append(codeContent);
        }).doOnComplete(() -> {
            try {
                String CompleteHtmlCode = sb.toString();
                HtmlCodeResult htmlCodeResult = CodeParser.parseHtmlCode(CompleteHtmlCode);
                CodeFileSaver.saveHtmlCodeResult(htmlCodeResult, appId);
                log.info("生成成功{}", CodeFileSaver.saveHtmlCodeResult(htmlCodeResult, appId).getAbsolutePath());
            } catch (Exception e) {
                log.error("生成失败", e.getMessage());
            }
        });
    }

    /**
     * 将 TokenStream 转换为 Flux<String>，并传递工具调用信息
     *
     * @param userMessage 用户消息
     * @param appId       应用ID
     * @return Flux<String> 流式响应（JSON格式的消息）
     */
    private Flux<String> generateAndSaveVueProjectCodeStream(String userMessage, long appId) {
        // 获取AI代码生成服务
        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory
                .getAiCodeGeneratorService(appId, CodeGenTypeEnum.VUE_PROJECT);

        // 获取token流
        TokenStream tokenStream = aiCodeGeneratorService.generateVueProjectCodeStream(appId, userMessage);
        return Flux.create(sink -> {
            tokenStream.onPartialResponse((String partialResponse) -> {
                        AiResponseMessage aiResponseMessage = new AiResponseMessage(partialResponse);
                        sink.next(JSONUtil.toJsonStr(aiResponseMessage));
                    })
                    .onPartialToolExecutionRequest((index, toolExecutionRequest) -> {
                        ToolRequestMessage toolRequestMessage = new ToolRequestMessage(toolExecutionRequest);
                        sink.next(JSONUtil.toJsonStr(toolRequestMessage));
                    })
                    .onToolExecuted((ToolExecution toolExecution) -> {
                        ToolExecutedMessage toolExecutedMessage = new ToolExecutedMessage(toolExecution);
                        sink.next(JSONUtil.toJsonStr(toolExecutedMessage));
                    })
                    .onCompleteResponse((ChatResponse response) -> {
                        sink.complete();
                    })
                    .onError((Throwable error) -> {
                        error.printStackTrace();
                        sink.error(error);
                    })
                    .start();
        });

    }



    /**
     * 统一入口：根据类型生成并保存代码
     *
     * @param userMessage     用户提示词
     * @param codeGenTypeEnum 生成类型
     * @return 保存的目录
     */

    public File generateAndSaveCode(String userMessage, CodeGenTypeEnum codeGenTypeEnum,long appId) {
        if (codeGenTypeEnum == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "生成类型为空");
        }
        return switch (codeGenTypeEnum) {
            case HTML -> generateAndSaveHtmlCode(userMessage,appId);
            case MULTI_FILE -> generateAndSaveMultiFileCode(userMessage,appId);
            default -> {
                String errorMessage = "不支持的生成类型：" + codeGenTypeEnum.getValue();
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, errorMessage);
            }
        };
    }

    private Flux<String> generateAndSaveMultiFileCodeStream(String userMessage ,long appId) {
        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appId, CodeGenTypeEnum.MULTI_FILE);
        Flux<String> result = aiCodeGeneratorService.generateMultiFileCodeStream(userMessage);
        StringBuffer sb = new StringBuffer();
        return result.doOnNext(codeContent -> {
            sb.append(codeContent);
        }).doOnComplete(()->{
            try {
                String CompleteHtmlCode = sb.toString();
                MultiFileCodeResult multiFileCodeResult = CodeParser.parseMultiFileCode(CompleteHtmlCode);
                CodeFileSaver.saveMultiFileCodeResult(multiFileCodeResult,appId);
                log.info("生成多文件代码成功{}",CodeFileSaver.saveMultiFileCodeResult(multiFileCodeResult,appId).getAbsolutePath());
            }catch (Exception e){
                log.error("生成多文件代码失败",e.getMessage());
            }
        });
    }

    private Flux<String> generateAndSaveHtmlCodeStream(String userMessage,long appId) {
        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appId,CodeGenTypeEnum.HTML);
        Flux<String> result = aiCodeGeneratorService.generateHtmlCodeStream(userMessage);
        StringBuffer sb = new StringBuffer();
     return result.doOnNext(codeContent -> {
            sb.append(codeContent);
        }).doOnComplete(()->{
            try {
                String CompleteHtmlCode = sb.toString();
                HtmlCodeResult htmlCodeResult = CodeParser.parseHtmlCode(CompleteHtmlCode);
                CodeFileSaver.saveHtmlCodeResult(htmlCodeResult,appId);
                log.info("生成HTML代码成功{}",CodeFileSaver.saveHtmlCodeResult(htmlCodeResult,appId).getAbsolutePath());
            }catch (Exception e){
                log.error("生成HTML代码失败",e.getMessage());
            }
        });
    }

    /**
     * 生成 HTML 模式的代码并保存
     *
     * @param userMessage 用户提示词
     * @return 保存的目录
     */
    private File generateAndSaveHtmlCode(String userMessage,long appId) {
        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appId,CodeGenTypeEnum.HTML);
        HtmlCodeResult result = aiCodeGeneratorService.generateHtmlCode(userMessage);
        return CodeFileSaver.saveHtmlCodeResult(result,appId);
    }

    /**
     * 生成多文件模式的代码并保存
     *
     * @param userMessage 用户提示词
     * @return 保存的目录
     */
    private File generateAndSaveMultiFileCode(String userMessage,long appId) {
        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appId, CodeGenTypeEnum.MULTI_FILE);
        MultiFileCodeResult result = aiCodeGeneratorService.generateMultiFileCode(userMessage);
        return CodeFileSaver.saveMultiFileCodeResult(result,appId);
    }


}
